昨天是簡單的API範例,今天要實現更進階的 API 應用,擴展 API 功能,並使用 Ngrok 將它公開給其他用戶。進階應用包括 API 的多路由、身份驗證,以及與第三方服務的集成。
以下是一個進階的 API 應用示例,結合 Flask 和 Ngrok,並展示如何進行身份驗證、處理不同的 HTTP 請求方法,以及利用 Ngrok 讓外部用戶可以訪問 API。
pip install flask ngrok pyngrok
from flask import Flask, jsonify, request, abort
from pyngrok import ngrok
app = Flask(__name__)
# 模擬數據庫
users = {
    "user1": {"name": "Alice", "age": 30},
    "user2": {"name": "Bob", "age": 25}
}
# 身份驗證
def check_auth(token):
    # 假設的 API token 驗證
    return token == "secret-token"
@app.route('/api/users', methods=['GET'])
def get_users():
    token = request.headers.get('Authorization')
    if not check_auth(token):
        return abort(401)  # Unauthorized
    return jsonify(users)
# 查詢特定用戶資料
@app.route('/api/users/<username>', methods=['GET'])
def get_user(username):
    token = request.headers.get('Authorization')
    if not check_auth(token):
        return abort(401)
    user = users.get(username)
    if user:
        return jsonify(user)
    else:
        return abort(404)  # Not Found
# 新增用戶資料
@app.route('/api/users', methods=['POST'])
def add_user():
    token = request.headers.get('Authorization')
    if not check_auth(token):
        return abort(401)
    if not request.json or not 'name' in request.json:
        return abort(400)  # Bad Request
    new_user = {
        "name": request.json["name"],
        "age": request.json.get("age", 0)
    }
    user_id = f"user{len(users) + 1}"
    users[user_id] = new_user
    return jsonify({user_id: new_user}), 201  # Created
# 啟動 ngrok 並公開 API
if __name__ == "__main__":
    # 啟動 Ngrok 隧道
    public_url = ngrok.connect(5000)
    print(" * Public URL:", public_url)
    # 運行 Flask 應用
    app.run(port=5000)
Authorization 標頭中的 token,如果不匹配將返回 401 Unauthorized 狀態碼。/api/users 支持 GET 和 POST 方法。/api/users/<username> 支持 GET 方法,來查詢特定用戶資料。400 Bad Request 或 404 Not Found 錯誤,來處理無效的請求。運行這個 Python 應用後,你會在終端中看到此輸出:
* Public URL: http://xxxxxxxx.ngrok-free.app
此時,Ngrok 已經為你的本地 API 創建了一個公開的 URL。你可以將這個 URL 發送給外部用戶,讓他們訪問 API。
你可以使用 Postman 或curl來進行測試:
如果你正在使用 Postman 來測試這個 API,設置如下:
GET 或 POST)。http://xxxxxxxx.ngrok-free.app/api/users
Authorization。secret-token。curl 發送請求在這個請求中,Authorization 標頭包含了 secret-token,這樣伺服器端的 Flask 應用就能識別這個請求來自於管理員,並根據管理員的角色授予相應的權限。
curl -H "Authorization: secret-token" http://xxxxxxxx.ngrok-free.app/api/users
基於角色的權限控制,讓不同的用戶具有不同的 API 使用權限,例如:
def check_auth(token, required_role=None):
    # 根據 token 驗證用戶角色
    if token == "admin-token":
        return required_role in ["admin", "user"]
    elif token == "user-token":
        return required_role == "user"
    return False
使用 Flask-RESTful 和 flasgger 生成 Swagger 文檔,讓使用者可以通過網頁介面直接查看和測試 API。
安裝必要套件:
pip install flask-restful flasgger
集成 Flask-RESTful 和 flasgger:
from flask import Flask
from flask_restful import Api, Resource
from flasgger import Swagger
app = Flask(__name__)
api = Api(app)
swagger = Swagger(app)
class HelloWorld(Resource):
    def get(self):
        """
        This is an example endpoint.
        ---
        responses:
          200:
            description: A successful response
        """
        return {'hello': 'world'}
api.add_resource(HelloWorld, '/')
if __name__ == '__main__':
    app.run(debug=True)
訪問 Swagger 文檔:
在啟動 Flask 應用後,你可以在瀏覽器中打開 http://127.0.0.1:5000/apidocs 來查看 Swagger 自動生成的 API 文檔。這將顯示所有已定義的 API 路徑以及它們的描述,讓你可以測試不同的 API 調用。
你可以使用 Authlib 來集成 OAuth 2.0,為你的 API 提供更高的安全性。
Authlibpip install authlib
from authlib.integrations.flask_oauth2 import AuthorizationServer, ResourceProtector
from authlib.oauth2.rfc6749 import grants
from flask import Flask
app = Flask(__name__)
# 假設你已經有一個 Authorization Server 設定
server = AuthorizationServer(app)
@app.route('/api/protected')
def protected():
    # 需要 OAuth 認證
    return {'message': 'This is a protected route'}
if __name__ == '__main__':
    app.run(debug=True)

為了防止 API 被濫用,你可以使用 Flask-Limiter 來限制每個 IP 的請求次數。
安裝 Flask-Limiter:
pip install Flask-Limiter
集成 Flask-Limiter:
from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter(app, key_func=get_remote_address)
@app.route('/api')
@limiter.limit("5 per minute")
def index():
    return 'This route is limited to 5 requests per minute'
if __name__ == '__main__':
    app.run(debug=True)

這樣可以限制每個 IP 每分鐘只能訪問 5 次,防止濫用。